<template>
  <div class="hq-tp">
    <div ref="hqTP" class="hq-tp_container">
      <div class="hq-tp_container_head">
        <span v-if="props.title" style="color: #333">{{ props.title }}:</span>
        <slot v-else name="headerTitle"></slot>
        <slot name="headerAction"></slot>
      </div>
      <div
        v-loading.lock="props.loading"
        class="hq-tp_container_table"
        element-loading-background="rgba(255, 255, 255, 0)"
        element-loading-spinner="el-icon-loading"
        element-loading-text="加载中"
      >
        <el-table
          class="el-table"
          :data="props.list"
          :max-height="maxHeight"
          v-bind="packedTableAttrs"
          @selection-change="emit('selection-change', $event)"
          @sort-change="emit('sort-change', $event)"
        >
          <template v-for="column in props.columns" :key="column.prop">
            <el-table-column
              v-if="!column.slot"
              v-bind="{ ...packedColumnAttrs, ...column }"
            >
            </el-table-column>
            <el-table-column
              v-else
              v-bind="{ ...packedColumnAttrs, ...column }"
            >
              <template #default="scope">
                <slot :row="scope.row" :name="column.prop"> </slot>
              </template>
            </el-table-column>
          </template>
        </el-table>
      </div>
      <div v-if="!props.hidePage" class="hq-tp_container_pagination">
        <el-pagination
          :current-page="props.currentPage"
          :page-size="props.pageSize"
          :page-sizes="props.pageSizes"
          :layout="props.layout"
          :total="props.total"
          @size-change="sizeChange"
          @current-change="currentChange"
        >
        </el-pagination>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'

type T = Record<string, string | boolean | number>

interface IProps {
  title?: string
  list: T[]
  columns: T[]
  maxHeight?: string | number
  tableAttrs?: Record<string, string | number | boolean | T>
  loading?: boolean
  countHeight?: boolean
  currentPage?: number
  pageSize?: number
  total?: number
  layout?: string
  pageSizes?: number[]
  hidePage?: boolean
}

const props = withDefaults(defineProps<IProps>(), {
  title: '',
  list: () => [],
  columns: () => [],
  maxHeight: 0,
  tableAttrs: () => ({}),
  loading: false,
  countHeight: true,
  currentPage: 1,
  pageSize: 10,
  total: 0,
  layout: 'total, sizes, prev, pager, next, jumper',
  pageSizes: () => [10, 20, 50],
  hidePage: false
})

/**
 * 合并table属性属性
 */
const tableAttrs = { border: true }
const packedTableAttrs = (Object as any).assign(tableAttrs, props.tableAttrs)

/**
 * 合并column属性
 */
const packedColumnAttrs = { align: 'center' }

/**
 * 计算高度
 * 初始化 window变化会自动计算高度，其他变更的高度计算需要主动触发 (无法监听到容器大小的变化)
 * 1、请求数据以后
 * 2、容器大小变化后
 */
const hqTP = ref(0)
const maxHeight = ref(props.maxHeight)
function onCountHeight() {
  nextTick(() => {
    const $hqTP: any = hqTP.value
    if ($hqTP.clientHeight) {
      maxHeight.value =
        packedTableAttrs.maxHeight ||
        $hqTP.clientHeight - (props.hidePage ? 40 : 96)
    }
  })
}
watch(() => props.countHeight, onCountHeight)
onMounted(() => {
  window.addEventListener('resize', onCountHeight)
  onCountHeight()
})
onBeforeUnmount(() => {
  window.removeEventListener('resize', onCountHeight)
})

/**
 * 分页
 */
const emit = defineEmits([
  'sizeChange',
  'currentChange',
  'sort-change',
  'selection-change'
])
function sizeChange(v: number) {
  emit('sizeChange', v)
}
function currentChange(v: number) {
  emit('currentChange', v)
}
</script>
<style scoped lang="scss">
.hq-tp {
  box-sizing: border-box;
  position: relative;
  display: flex;
  flex: 1;
  &_container {
    position: absolute;
    height: 100%;
    width: 100%;
    box-sizing: border-box;
    &_head {
      height: 40px;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }
    &_table {
      flex: 1;
      position: relative;
      :deep() .el-table__header {
        th {
          background-color: #f5f5f5;
          font-size: 12px;
        }
      }
      :deep() .el-table__row td,
      :deep().el-table__row span {
        font-size: 12px;
      }
    }
    &_pagination {
      height: 56px;
      position: relative;
      :deep() .el-pagination {
        position: absolute;
        top: 10px;
        right: 0;
      }
    }
  }
}
</style>
